{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pandas 添加行\n",
    "\n",
    "本教程详细介绍如何在 Pandas DataFrame 中添加新行的各种方法。\n",
    "\n",
    "## 目录\n",
    "1. 使用 loc 添加行\n",
    "2. 使用 append() 方法（已弃用）\n",
    "3. 使用 concat() 添加行\n",
    "4. 使用 pd.concat() 批量添加\n",
    "5. 使用 DataFrame 构造函数\n",
    "6. 性能对比和最佳实践"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 导入库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 使用 loc 添加行\n",
    "\n",
    "### 方法说明\n",
    "\n",
    "使用 `loc` 可以通过指定新的索引来添加行。\n",
    "\n",
    "**语法:**\n",
    "```python\n",
    "df.loc[新索引] = [值1, 值2, ...]\n",
    "```\n",
    "\n",
    "**特点:**\n",
    "- ✅ 简单直观\n",
    "- ✅ 直接修改原 DataFrame\n",
    "- ✅ 可以指定索引\n",
    "- ❌ 一次只能添加一行\n",
    "- ❌ 需要提供所有列的值\n",
    "\n",
    "**适用场景:** 快速添加单行数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 创建示例数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame({\n",
    "    '姓名': ['张三', '李四'],\n",
    "    '年龄': [25, 30],\n",
    "    '城市': ['北京', '上海']\n",
    "})\n",
    "\n",
    "print(\"原始 DataFrame:\")\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例2: 使用 loc 添加单行（数字索引）\n",
    "\n",
    "在末尾添加新行，索引为 2。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.loc[2] = ['王五', 35, '广州']\n",
    "print(\"添加一行后:\")\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例3: 使用 loc 添加行（自定义索引）\n",
    "\n",
    "可以使用字符串或其他类型作为索引。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_custom = pd.DataFrame({\n",
    "    '姓名': ['张三', '李四'],\n",
    "    '年龄': [25, 30],\n",
    "    '城市': ['北京', '上海']\n",
    "}, index=['A', 'B'])\n",
    "\n",
    "df_custom.loc['C'] = ['王五', 35, '广州']\n",
    "print(\"使用自定义索引:\")\n",
    "print(df_custom)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例4: 使用字典添加行\n",
    "\n",
    "可以使用字典指定列名和值，更清晰。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_dict = pd.DataFrame({\n",
    "    '姓名': ['张三', '李四'],\n",
    "    '年龄': [25, 30],\n",
    "    '城市': ['北京', '上海']\n",
    "})\n",
    "\n",
    "df_dict.loc[len(df_dict)] = {'姓名': '赵六', '年龄': 40, '城市': '深圳'}\n",
    "print(\"使用字典添加:\")\n",
    "print(df_dict)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例5: 注意事项 - 列数必须匹配\n",
    "\n",
    "⚠️ 提供的值数量必须与列数匹配。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "try:\n",
    "    df.loc[3] = ['孙七', 45]  # 只提供2个值，但有3列\n",
    "except ValueError as e:\n",
    "    print(f\"错误: {e}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 使用 append() 方法\n",
    "\n",
    "### 方法说明\n",
    "\n",
    "⚠️ **重要提示**: `append()` 方法在 Pandas 2.0+ 中已被弃用，推荐使用 `concat()`。\n",
    "\n",
    "**语法:**\n",
    "```python\n",
    "df.append(new_row, ignore_index=True)\n",
    "```\n",
    "\n",
    "**参数:**\n",
    "- `ignore_index`: 是否重置索引（默认 False）\n",
    "- `verify_integrity`: 是否检查索引重复\n",
    "\n",
    "**特点:**\n",
    "- ❌ 已弃用（Pandas 2.0+）\n",
    "- ✅ 返回新 DataFrame\n",
    "- ✅ 可以添加字典或 Series\n",
    "- ❌ 性能较差（每次都创建新对象）\n",
    "\n",
    "**适用场景:** 不推荐使用，仅作了解"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 使用 append() 添加字典（仅供参考）\n",
    "\n",
    "注意：此方法已弃用，建议使用 concat()。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame({\n",
    "    '姓名': ['张三', '李四'],\n",
    "    '年龄': [25, 30],\n",
    "    '城市': ['北京', '上海']\n",
    "})\n",
    "\n",
    "# 旧方法（已弃用）\n",
    "# df_new = df.append({'姓名': '王五', '年龄': 35, '城市': '广州'}, ignore_index=True)\n",
    "\n",
    "# 推荐使用 concat 替代\n",
    "new_row = pd.DataFrame([{'姓名': '王五', '年龄': 35, '城市': '广州'}])\n",
    "df_new = pd.concat([df, new_row], ignore_index=True)\n",
    "\n",
    "print(\"添加行后:\")\n",
    "print(df_new)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 使用 concat() 添加行\n",
    "\n",
    "### 方法说明\n",
    "\n",
    "`pd.concat()` 是推荐的添加行方法，可以拼接多个 DataFrame。\n",
    "\n",
    "**语法:**\n",
    "```python\n",
    "pd.concat([df1, df2, ...], axis=0, ignore_index=False)\n",
    "```\n",
    "\n",
    "**参数:**\n",
    "- `axis=0`: 纵向拼接（添加行）\n",
    "- `axis=1`: 横向拼接（添加列）\n",
    "- `ignore_index`: 是否重置索引\n",
    "- `keys`: 添加层级索引\n",
    "\n",
    "**特点:**\n",
    "- ✅ 官方推荐方法\n",
    "- ✅ 可以批量添加多行\n",
    "- ✅ 性能较好\n",
    "- ✅ 返回新 DataFrame\n",
    "\n",
    "**适用场景:** 添加一行或多行数据（推荐）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 使用 concat() 添加单行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame({\n",
    "    '姓名': ['张三', '李四'],\n",
    "    '年龄': [25, 30],\n",
    "    '城市': ['北京', '上海']\n",
    "})\n",
    "\n",
    "# 创建新行（作为 DataFrame）\n",
    "new_row = pd.DataFrame([{'姓名': '王五', '年龄': 35, '城市': '广州'}])\n",
    "\n",
    "# 使用 concat 添加\n",
    "df_new = pd.concat([df, new_row], ignore_index=True)\n",
    "print(\"添加单行:\")\n",
    "print(df_new)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例2: 使用 concat() 添加多行\n",
    "\n",
    "可以一次性添加多行数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建多行数据\n",
    "new_rows = pd.DataFrame([\n",
    "    {'姓名': '赵六', '年龄': 40, '城市': '深圳'},\n",
    "    {'姓名': '孙七', '年龄': 28, '城市': '杭州'},\n",
    "    {'姓名': '周八', '年龄': 33, '城市': '成都'}\n",
    "])\n",
    "\n",
    "df_new = pd.concat([df, new_rows], ignore_index=True)\n",
    "print(\"添加多行:\")\n",
    "print(df_new)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例3: 保留原索引\n",
    "\n",
    "不使用 `ignore_index`，保留原有索引。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df1 = pd.DataFrame({\n",
    "    '姓名': ['张三', '李四'],\n",
    "    '年龄': [25, 30]\n",
    "}, index=['A', 'B'])\n",
    "\n",
    "df2 = pd.DataFrame({\n",
    "    '姓名': ['王五'],\n",
    "    '年龄': [35]\n",
    "}, index=['C'])\n",
    "\n",
    "df_combined = pd.concat([df1, df2])\n",
    "print(\"保留原索引:\")\n",
    "print(df_combined)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例4: 处理列不匹配的情况\n",
    "\n",
    "concat 会自动处理列不完全匹配的情况。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df1 = pd.DataFrame({\n",
    "    '姓名': ['张三', '李四'],\n",
    "    '年龄': [25, 30]\n",
    "})\n",
    "\n",
    "df2 = pd.DataFrame({\n",
    "    '姓名': ['王五'],\n",
    "    '城市': ['广州']  # 不同的列\n",
    "})\n",
    "\n",
    "df_combined = pd.concat([df1, df2], ignore_index=True)\n",
    "print(\"列不匹配时:\")\n",
    "print(df_combined)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. 使用 pd.concat() 批量添加\n",
    "\n",
    "### 方法说明\n",
    "\n",
    "当需要添加大量行时，应该批量操作而不是逐行添加。\n",
    "\n",
    "**性能建议:**\n",
    "- ❌ 避免在循环中逐行添加\n",
    "- ✅ 收集所有行，然后一次性 concat\n",
    "\n",
    "**适用场景:** 需要添加大量行时"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 错误方式 - 循环中逐行添加（慢）\n",
    "\n",
    "⚠️ 这种方式性能很差，不推荐。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 不推荐的方式\n",
    "df = pd.DataFrame(columns=['姓名', '年龄', '城市'])\n",
    "\n",
    "# 模拟添加多行\n",
    "data_to_add = [\n",
    "    {'姓名': '张三', '年龄': 25, '城市': '北京'},\n",
    "    {'姓名': '李四', '年龄': 30, '城市': '上海'},\n",
    "    {'姓名': '王五', '年龄': 35, '城市': '广州'}\n",
    "]\n",
    "\n",
    "# 错误方式：在循环中逐行添加\n",
    "start = time.time()\n",
    "for row in data_to_add:\n",
    "    new_row = pd.DataFrame([row])\n",
    "    df = pd.concat([df, new_row], ignore_index=True)\n",
    "time_slow = time.time() - start\n",
    "\n",
    "print(\"循环添加结果:\")\n",
    "print(df)\n",
    "print(f\"\\n耗时: {time_slow:.6f} 秒\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例2: 正确方式 - 批量添加（快）\n",
    "\n",
    "✅ 推荐方式：先收集所有数据，然后一次性添加。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 推荐的方式\n",
    "df = pd.DataFrame(columns=['姓名', '年龄', '城市'])\n",
    "\n",
    "# 同样的数据\n",
    "data_to_add = [\n",
    "    {'姓名': '张三', '年龄': 25, '城市': '北京'},\n",
    "    {'姓名': '李四', '年龄': 30, '城市': '上海'},\n",
    "    {'姓名': '王五', '年龄': 35, '城市': '广州'}\n",
    "]\n",
    "\n",
    "# 正确方式：批量添加\n",
    "start = time.time()\n",
    "new_rows = pd.DataFrame(data_to_add)\n",
    "df = pd.concat([df, new_rows], ignore_index=True)\n",
    "time_fast = time.time() - start\n",
    "\n",
    "print(\"批量添加结果:\")\n",
    "print(df)\n",
    "print(f\"\\n耗时: {time_fast:.6f} 秒\")\n",
    "\n",
    "if time_slow > 0:\n",
    "    print(f\"\\n批量添加快 {time_slow/time_fast:.1f} 倍\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. 使用 DataFrame 构造函数\n",
    "\n",
    "### 方法说明\n",
    "\n",
    "有时候，直接创建新的 DataFrame 比添加行更高效。\n",
    "\n",
    "**适用场景:**\n",
    "- 需要完全重建 DataFrame\n",
    "- 数据来源是列表或字典\n",
    "\n",
    "**特点:**\n",
    "- ✅ 性能最好\n",
    "- ✅ 代码简洁\n",
    "- ✅ 适合批量操作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 从列表创建 DataFrame"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 原始数据\n",
    "data = [\n",
    "    ['张三', 25, '北京'],\n",
    "    ['李四', 30, '上海']\n",
    "]\n",
    "\n",
    "df = pd.DataFrame(data, columns=['姓名', '年龄', '城市'])\n",
    "print(\"从列表创建:\")\n",
    "print(df)\n",
    "\n",
    "# 添加新数据\n",
    "data.append(['王五', 35, '广州'])\n",
    "df = pd.DataFrame(data, columns=['姓名', '年龄', '城市'])\n",
    "print(\"\\n添加后:\")\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例2: 从字典列表创建"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 字典列表\n",
    "data = [\n",
    "    {'姓名': '张三', '年龄': 25, '城市': '北京'},\n",
    "    {'姓名': '李四', '年龄': 30, '城市': '上海'}\n",
    "]\n",
    "\n",
    "df = pd.DataFrame(data)\n",
    "print(\"从字典列表创建:\")\n",
    "print(df)\n",
    "\n",
    "# 添加新数据\n",
    "data.append({'姓名': '王五', '年龄': 35, '城市': '广州'})\n",
    "df = pd.DataFrame(data)\n",
    "print(\"\\n添加后:\")\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. 性能对比和最佳实践\n",
    "\n",
    "不同方法的性能对比和使用建议。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 性能测试: 添加 1000 行数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "\n",
    "# 准备测试数据\n",
    "test_data = [{'姓名': f'用户{i}', '年龄': 20+i%50, '城市': '北京'} for i in range(1000)]\n",
    "\n",
    "# 方法1: 循环使用 loc（最慢）\n",
    "df1 = pd.DataFrame(columns=['姓名', '年龄', '城市'])\n",
    "start = time.time()\n",
    "for i, row in enumerate(test_data):\n",
    "    df1.loc[i] = [row['姓名'], row['年龄'], row['城市']]\n",
    "time_loc = time.time() - start\n",
    "\n",
    "# 方法2: 循环使用 concat（慢）\n",
    "df2 = pd.DataFrame(columns=['姓名', '年龄', '城市'])\n",
    "start = time.time()\n",
    "for row in test_data:\n",
    "    df2 = pd.concat([df2, pd.DataFrame([row])], ignore_index=True)\n",
    "time_concat_loop = time.time() - start\n",
    "\n",
    "# 方法3: 批量 concat（快）\n",
    "df3 = pd.DataFrame(columns=['姓名', '年龄', '城市'])\n",
    "start = time.time()\n",
    "new_df = pd.DataFrame(test_data)\n",
    "df3 = pd.concat([df3, new_df], ignore_index=True)\n",
    "time_concat_batch = time.time() - start\n",
    "\n",
    "# 方法4: 直接创建（最快）\n",
    "start = time.time()\n",
    "df4 = pd.DataFrame(test_data)\n",
    "time_direct = time.time() - start\n",
    "\n",
    "print(\"性能对比（添加 1000 行）:\")\n",
    "print(f\"方法1 - 循环 loc:        {time_loc:.4f} 秒\")\n",
    "print(f\"方法2 - 循环 concat:     {time_concat_loop:.4f} 秒\")\n",
    "print(f\"方法3 - 批量 concat:     {time_concat_batch:.4f} 秒\")\n",
    "print(f\"方法4 - 直接创建:        {time_direct:.4f} 秒\")\n",
    "print(f\"\\n最快方法是最慢方法的 {max(time_loc, time_concat_loop) / time_direct:.0f} 倍\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 最佳实践总结\n",
    "\n",
    "**推荐做法:**\n",
    "\n",
    "1. **添加单行**: 使用 `loc` 或 `concat()`\n",
    "   ```python\n",
    "   df.loc[len(df)] = [值1, 值2, ...]\n",
    "   # 或\n",
    "   df = pd.concat([df, pd.DataFrame([新行])], ignore_index=True)\n",
    "   ```\n",
    "\n",
    "2. **添加多行**: 使用批量 `concat()`\n",
    "   ```python\n",
    "   new_rows = pd.DataFrame([行1, 行2, ...])\n",
    "   df = pd.concat([df, new_rows], ignore_index=True)\n",
    "   ```\n",
    "\n",
    "3. **大量数据**: 直接创建新 DataFrame\n",
    "   ```python\n",
    "   df = pd.DataFrame(所有数据)\n",
    "   ```\n",
    "\n",
    "**避免的做法:**\n",
    "\n",
    "❌ 在循环中逐行添加\n",
    "❌ 使用已弃用的 `append()` 方法\n",
    "❌ 频繁修改 DataFrame 结构"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 实用技巧"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 技巧1: 在开头插入行\n",
    "df = pd.DataFrame({\n",
    "    '姓名': ['李四', '王五'],\n",
    "    '年龄': [30, 35]\n",
    "})\n",
    "\n",
    "new_row = pd.DataFrame([{'姓名': '张三', '年龄': 25}])\n",
    "df = pd.concat([new_row, df], ignore_index=True)\n",
    "print(\"在开头插入行:\")\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 技巧2: 在指定位置插入行\n",
    "df = pd.DataFrame({\n",
    "    '姓名': ['张三', '王五'],\n",
    "    '年龄': [25, 35]\n",
    "})\n",
    "\n",
    "# 在索引1的位置插入\n",
    "new_row = pd.DataFrame([{'姓名': '李四', '年龄': 30}])\n",
    "df = pd.concat([df.iloc[:1], new_row, df.iloc[1:]], ignore_index=True)\n",
    "print(\"\\n在中间插入行:\")\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 技巧3: 条件添加行\n",
    "df = pd.DataFrame({\n",
    "    '姓名': ['张三', '李四'],\n",
    "    '年龄': [25, 30]\n",
    "})\n",
    "\n",
    "# 只有年龄大于某个值时才添加\n",
    "new_data = {'姓名': '王五', '年龄': 35}\n",
    "if new_data['年龄'] > 30:\n",
    "    df = pd.concat([df, pd.DataFrame([new_data])], ignore_index=True)\n",
    "\n",
    "print(\"\\n条件添加:\")\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 总结\n",
    "\n",
    "### 添加行方法对比\n",
    "\n",
    "| 方法 | 性能 | 修改原数据 | 适用场景 | 推荐度 |\n",
    "|------|------|-----------|---------|--------|\n",
    "| `loc` | 中等 | 是 | 添加单行 | ⭐⭐⭐ |\n",
    "| `append()` | 差 | 否 | 已弃用 | ❌ |\n",
    "| `concat()` 单行 | 中等 | 否 | 添加单行 | ⭐⭐⭐⭐ |\n",
    "| `concat()` 批量 | 好 | 否 | 添加多行 | ⭐⭐⭐⭐⭐ |\n",
    "| 直接创建 | 最好 | - | 批量数据 | ⭐⭐⭐⭐⭐ |\n",
    "\n",
    "### 关键要点\n",
    "\n",
    "1. **推荐使用 `concat()`** 而不是已弃用的 `append()`\n",
    "2. **批量操作** 比循环添加快得多\n",
    "3. **大量数据** 时直接创建 DataFrame 最快\n",
    "4. **使用 `ignore_index=True`** 重置索引\n",
    "5. **避免在循环中** 逐行添加数据\n",
    "6. **loc 方法** 适合快速添加单行\n",
    "7. **性能差异** 可达数百倍，选择正确的方法很重要"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
